import requests
import pandas as pd
import json
from selenium import webdriver
import datetime
import time
import redis
import threading
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr
from bs4 import BeautifulSoup as bs
from email.mime.multipart import MIMEMultipart
from email.header import Header
import configparser

config = configparser.ConfigParser()
config.read('config.ini', encoding='utf-8')  # 指定编码防止乱码:ml-citation{ref="3,7" data="citationList"}

web_location = r"D:\workSoftware\chromedriver"
from_name = config.get('DEFAULT', 'from_name')
web_url = config.get('DEFAULT', 'web_url')
date_time = config.getint('DEFAULT', 'date_time')
over_time = config.getint('DEFAULT', 'over_time')
date_file = config.get('DEFAULT', 'date_file')
error_number = config.get('DEFAULT', 'error_number')

redis_url = config.get('redis', 'host')
redis_port = config.getint('redis', 'port')
redis_pwd = config.get('redis', 'password')
expire_time = config.get('redis', 'expire_time')


from_addr = config.get('email', 'from_addr')
from_pwd = config.get('email', 'from_pwd')
smtp_addr = config.get('email', 'smtp_addr')
smtp_port = config.getint('email', 'smtp_port')

pool = redis.ConnectionPool(host=redis_url, port=redis_port, password=redis_pwd, decode_responses=True)
r = redis.Redis(connection_pool=pool)

def getMaxid(wd, user_name, password,requests):
    print(f'getMaxid.......')
    time.sleep(2)
    wd.find_element(By.XPATH, value="//*[@id='menu_wmc']").click()
    time.sleep(10)
    window_handles = wd.window_handles
    wd.switch_to.window(window_handles[1])
    time.sleep(10)
    getResponse(wd.get_log('performance'), "&p=get_wmc_list_bet".format(password),
                user_name)


def sendweb(user_name, password):
    print('sendweb.....')
    options = Options()
    caps = {
        "browserName": "chrome",
        'goog:loggingPrefs': {
            'performance': 'ALL',
            'driver': 'ALL'
        }  # 开启日志性能监听
    }
    for key, value in caps.items():
        options.set_capability(key, value)

    # 打开谷歌浏览器
    open = webdriver.ChromeOptions()
    open.add_argument(r"user-data-dir=./var/chrome-data")
    # 浏览器在电脑的路径
    open.binary_location = web_location
    open.add_argument('--headless')
    open.add_argument("--auto-open-devtools-for-tabs")
    wd = webdriver.Chrome(options=options)
    wd.execute_cdp_cmd("Network.enable", {})
    wd.execute_cdp_cmd("Network.setCacheDisabled", {"cacheDisabled": True})

    # 监听所有网络请求
    requests = []
    wd.execute_cdp_cmd("Network.requestWillBeSent", {
        "callback": lambda data: requests.append(data)
    })


    wd.get(web_url)
    time.sleep(5)
    wd.maximize_window()
    wd.find_element(By.XPATH, "//*[@id='btn_C']").click()
    user = wd.find_element(by=By.XPATH, value="//*[@id='username']")
    pwd = wd.find_element(by=By.XPATH, value="//*[@id='pwd']")
    time.sleep(0.2)
    user.send_keys(user_name)
    pwd.send_keys(password)
    time.sleep(0.2)
    wd.find_element(By.XPATH, value="//*[@id='loginBtn']").click()
    time.sleep(10)
    getMaxid(wd, user_name, password,requests)
    wd.close()
    wd.quit()


def get_evel_from_str(str):
    print(f'get_evel_from_str::「{str}')
    pairs = str.split('&')
    result_dict = {}
    for pair in pairs:
        # 通过等号分隔键和值
        key, value = pair.split("=")
        # 添加到字典中
        result_dict[key] = value
    return result_dict


def getResponse(login_log, param_tag, user_name):
    print('getResponse.....')
    data_key = "{}_data".format(user_name)
    header_key = "{}_header".format(user_name)
    ver_key = "{}_ver".format(user_name)
    # uid_key = "{}_uid".format(user_name)
    for i in range(len(login_log)):
        message = json.loads(login_log[i]['message'])
        params = message['message']['params']
        if 'type' in params.keys() and 'XHR' != params['type']:
            continue
        if 'method' in message.keys() and 'Network.requestWillBeSent' != message['method']:
            continue
        # .get() 方式获取是了避免字段不存在时报错
        request = params.get('request')
        if (request is None):
            continue
        data_ = request['postData']
        if param_tag not in data_:
            continue
        post_data = get_evel_from_str(data_)
        if (r.get(ver_key) is None):
            print(f'post_data set')
            r.set(ver_key, post_data['ver'], expire_time)
        else:
            print(f'sendWeb ver_key::{r.get(ver_key)}')

        if (r.get(data_key) is None):
            print(f'data_key set')
            r.set(data_key, str(post_data), expire_time)
        else:
            print(f'sendWeb ver_key::{r.get(data_key)}')

        if (r.get(header_key) is None):
            print(f'header_key set')
            r.set(header_key, str(request['headers']), expire_time)
        else:
            print(f'sendWeb ver_key::{r.get(header_key)}')


def get_ver(user_name, pwd):
    ver_key = "{}_ver".format(user_name)
    if (r.get(ver_key) is None):
        sendweb(user_name, pwd)
    return r.get(ver_key)


def get_data(user_name, pwd):
    data_key = "{}_data".format(user_name)
    if (r.get(data_key) is None):
        sendweb(user_name, pwd)
    return eval(r.get(data_key))


def get_header(user_name, pwd):
    header_key = "{}_header".format(user_name)
    if (r.get(header_key) is None):
        sendweb(user_name, pwd)
    return eval(r.get(header_key))


def clear_redis(user_name):
    data_key = "{}_data".format(user_name)
    ver_key = "{}_ver".format(user_name)
    header_key = "{}_header".format(user_name)
    retry_key = "{}_retry_number".format(user_name)
    r.delete(data_key)
    r.delete(ver_key)
    r.delete(header_key)
    r.delete(retry_key)


def getData(user,name: str, pwd: str, email: list):
    try:
        if (0 != user['status']):
            return
        data = get_data(name, pwd)
        header = get_header(name, pwd)
        print(f'send_user::{name}  send_time::{datetime.datetime.now().strftime("%Y%m%d:%H:%M:%S")}')
        print(f'data::{data}')
        print(f'header::{header}')
        send_detail(user,name, pwd, email)
    except Exception as e:
        print('getData::操作失败，继续获取::' + str(e))


# def send_mail(to_adds, send_title, send_msg):
#     try:
#         # 创建MIME文本对象并添加内容
#         msg = MIMEText(send_msg)
#         msg['Subject'] = send_title
#         msg['From'] = formataddr([from_name, from_addr])
#         msg['To'] = ', '.join(to_adds)
#
#         # 连接到SMTP服务器并进行身份认证
#         server = smtplib.SMTP(smtp_addr, smtp_port)
#         server.starttls()
#         server.login(from_addr, from_pwd)
#
#         # 发送邮件
#         server.sendmail(from_addr, to_adds, msg.as_string())
#         print('邮件已成功发送！')
#     except Exception as e:
#         print('发送邮件时出现错误：', str(e))
#     finally:
#         # 关闭与SMTP服务器的连接
#         server.quit()

def send_mail(to_addr, send_title, send_msg):
    print(f'to_addr::{to_addr}  send_title::{send_title}  send_msg::{send_msg}')
    # 创建一个实例msg
    msg = MIMEMultipart()
    msg['From'] = formataddr([from_name, from_addr])
    msg['To'] = ', '.join(to_addr)
    msg['Subject'] = send_title
    # 邮件正文内容
    msg.attach(MIMEText(send_msg, 'html', 'utf-8'))
    try:
        smtpobj = smtplib.SMTP_SSL(smtp_addr)
        smtpobj.connect(smtp_addr, smtp_port)  # 建立连接--qq邮箱服务和端口号
        smtpobj.login(from_addr, from_pwd)  # 登录--发送者账号和口令
        smtpobj.sendmail(from_addr, to_addr, msg.as_string())
        print("邮件发送成功")
    except smtplib.SMTPException as e:
        print("无法发送邮件:", e)
    finally:
        # 关闭服务器
        smtpobj.quit()

def save_data(user, email, data):
    # key:账号：单号：地址
    print('save_data.....')
    fbk2 = data['TID']
    to_adds = []
    for i in range(len(email)):
        redis_key = "{}:{}:{}:".format(user, fbk2, email[i])
        if r.get(redis_key) is None:
            to_adds.append(email[i])

    if len(to_adds) < 1:
        print('save_data邮件已发送.....')
        return
    fbk1 = data['DATE'] + ' ' + data['TIME']
    td2str = data['NAME0']
    fbk7 = data['WAGERSTYPE']
    fbk8 = data['GT']
    # fbk10 = data['SHOWTEXT_LEAGUE']
    # fbk13 = data['SHOWTEXT_TEAM_NUM']
    # fbk11 = data['SHOWTEXT_TEAM']
    # fbk16 = data['SHOWTEXT_ORDER_TYPE_IORATIO']
    bs_info = bs(data['TNAME'], 'html.parser')

    find_li = bs_info.find_all('li', )
    if len(find_li) == 1:
        fbk10 = find_li[0].text
        fbk13 = ''
        fbk11 = ''
        fbk16 = ''
    else:
        fbk13 = find_li[0].text
        fbk11 = find_li[1].text
        fbk16 = find_li[2].text
        fbk10 = data['SHOWTEXT_LEAGUE']
    td5str = data['GOLD']

    html_template = """
       <p> 时间：{fbk1}</p>
       <p>会员：{td2str}</p>
       <p>单号：{fbk2}</p>
       <p>{fbk8}:{fbk7}</p>
        <p></p>
        <p>内容：</p>
        <p>{fbk10}</p>
        <p>{fbk13}</p>
        <p>{fbk11}</p>
        <p>{fbk16}</p>
        <p></p>
        <p>¥： {td5str}</p>
    """
    html_content = html_template.format(fbk1=fbk1, td2str=td2str, fbk2=fbk2, fbk7=fbk7, fbk8=fbk8, fbk10=fbk10,
                                        fbk11=fbk11, fbk13=fbk13, fbk16=fbk16, td5str=td5str)
    my_msg = "会员：" + td2str + "单号：" + fbk2
    send_mail(to_adds, my_msg, html_content)
    for i in to_adds:
        redis_key = "{}:{}:{}:".format(user, fbk2, i)
        r.set(redis_key, fbk2)


def send_detail(user,name: str, pwd: str, email: list):
    data = get_data(name, pwd)
    header = get_header(name, pwd)
    ver = get_ver(name, pwd)
    session = requests.session()
    retry_key = "{}_retry_number".format(name)
    sendUrl = "{}/transform.php?ver={}".format(web_url,ver)
    print(f'send_detail{send_detail}')
    get = 1
    try:
        response = session.post(sendUrl, data=data, headers=header, timeout=(5))
        print(f'response::{response.text}')
        if 'wagers' in response.text:
            resultJson = json.loads(response.text)
            maxid_ = resultJson['maxid']
            r.set('maxid', maxid_)
            wagers_ = resultJson['wagers']
            for i in range(len(wagers_)):
                print(f'wagers_[{i}]::{wagers_[i]}')
                # 处理数据，并发送邮件。
                save_data(name, email, wagers_[i])
            print(f'------------------------------------------')
        elif 'status' in response.text:
            resultJson = json.loads(response.text)
            status_ = resultJson['status']
            if status_ == "error":
                state_key = "state:" + name
                user['status'] = 2
                update_date(user['id'])
                r.set(state_key,user,over_time)
            clear_redis(name)
        else:
            clear_redis(name)
    except Exception as e:
        if (r.get(retry_key) is not None):
            get = int(r.get(retry_key))
            if get == error_number:
                clear_redis(name)
                getData(user,name, pwd, email)
            get = get + 1
        r.set(retry_key, get)
        print(f'send_detail:: error_site::{get} 操作失败，继续获取::{str(e)}')

def update_date(number):
    df = pd.read_excel(date_file)
    row_index_to_modify = number - 1  # 转换为DataFrame的索引
    if row_index_to_modify < len(df):
        # 检查列名是否存在
        if '用户名' in df.columns and '密码' in df.columns:
            # 修改用户名和密码列的值
            df.at[row_index_to_modify, '状态'] = 3
            print(f"已修改行 {number} 的状态'")
        else:
            print(f"警告：文件中未找到'用户名'或'密码'列，无法修改。")
    else:
        print(f"警告：行号 {number} 超出范围，无法修改。")

    # 保存修改后的Excel文件
    output_file_path = 'account.xlsx'  # 输出文件名
    df.to_excel(output_file_path, index=False)  # index=False表示不保存行索引
    print(f"\n修改后的数据已保存到: {output_file_path}")

def get_login_info():
    df = pd.read_excel(date_file)
    # print("原始数据预览：")
    users = []
    for index, row in df.iterrows():  # 逐行迭代
        # print(f"\n行 {index} 数据：")
        user={}
        for col in df.columns:  # 遍历每一列
            if("序号" == col):
                user['id'] = row[col]
            elif("用户名"==col):
                user['name'] = row[col]
            elif("密码"==col):
                user['pwd'] = row[col]
            elif("邮箱"==col):
                user['email'] = row[col]
            elif("状态"==col):
                user['status'] = row[col]
            # print(f"{col}: {row[col]}")  # 输出列名和值
        users.append(user)
    return users

def main():
    threads = []
    while 1 == 1:
        df = get_login_info()
        for i in range(len(df)):
            name = df[i]['name']
            pwd = df[i]['pwd']
            email = df[i]['email'].split(",")
            print(f'name:{name} , password:{pwd} status:{df[i]["status"]} login web')
            t = threading.Thread(target=getData(df[i],name, pwd, email))
            threads.append(t)
            t.start()
            time.sleep(10)
    # 等待所有线程结束
    for t in threads:
        t.join()


if __name__ == "__main__":
    main()
